package com.qys.training.biz.utils;

import org.apache.http.entity.ContentType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 文件工具，封装了一些对文件的操作
 *
 * @author Winstone
 * @date 2020/8/4 - 2:34 下午
 */
public class FileUtil {

    /**
     * 将流写入指定地址
     *
     * @param stream
     * @param path
     * @throws IOException
     */
    public static void writeFileTo(InputStream stream, String path) throws IOException {
        File file = new File(path);
        mkdir(file);
        OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
        write(stream, outputStream);
    }

    /**
     * 流的写入
     *
     * @param in
     * @param out
     * @throws IOException
     */
    public static void write(InputStream in, OutputStream out) throws IOException {
        byte[] bytes = new byte[1024];
        int length;
        try {
            while ((length = in.read(bytes)) != -1) {
                out.write(bytes, 0, length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            in.close();
            out.close();
        }
    }

    // 根据文件创建路径
    public static void mkdir(File file) {
        if (!file.exists() && !file.isDirectory()) {
            File parent = new File(file.getParent());
            parent.mkdir();
        }
    }

    /**
     * 获取文件Hash
     *
     * @param fis
     * @return
     */
    public static String getFileHash(InputStream fis) {
        try {
            //拿到一个MD5转换器,如果想使用SHA-1或SHA-256，则传入SHA-1,SHA-256
            MessageDigest md = MessageDigest.getInstance("MD5");

            //分多次将一个文件读入，对于大型文件而言，比较推荐这种方式，占用内存比较少。
            byte[] buffer = new byte[1024];
            int length = -1;
            while ((length = fis.read(buffer, 0, 1024)) != -1) {
                md.update(buffer, 0, length);
            }
            fis.close();
            //转换并返回包含16个元素字节数组,返回数值范围为-128到127
            byte[] md5Bytes = md.digest();
            BigInteger bigInt = new BigInteger(1, md5Bytes);//1代表绝对值
            return bigInt.toString(16);//转换为16进制
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /***
     * 将多个文件压缩成Zip流
     * @param srcFiles
     */
    public static void zipFiles(File[] srcFiles, OutputStream outputStream) {
        // 传入一个outputStream指向

        // 创建 ZipOutputStream
        ZipOutputStream zipOutputStream;
        // 创建 FileInputStream 对象
        FileInputStream fileInputStream = null;

        try {
            zipOutputStream = new ZipOutputStream(outputStream);
            // 创建 ZipEntry 对象
            ZipEntry zipEntry = null;
            // 遍历源文件数组
            for (int i = 0; i < srcFiles.length; i++) {
                // 将源文件数组中的当前文件读入 FileInputStream 流中
                fileInputStream = new FileInputStream(srcFiles[i]);
                // 实例化 ZipEntry 对象，源文件数组中的当前文件
                zipEntry = new ZipEntry(srcFiles[i].getName());
                zipOutputStream.putNextEntry(zipEntry);
                // 该变量记录每次真正读的字节个数
                int len;
                // 定义每次读取的字节数组
                byte[] buffer = new byte[1024];
                while ((len = fileInputStream.read(buffer)) > 0) {
                    zipOutputStream.write(buffer, 0, len);
                }
            }

            zipOutputStream.closeEntry();
            zipOutputStream.close();
            fileInputStream.close();
            outputStream.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 拷贝文件操作
     *
     * @param sourcePath
     * @param copyPath
     * @throws IOException
     */
    public static void copyFile(String sourcePath, String copyPath) throws IOException {
        File copyFile = new File(copyPath);
        mkdir(copyFile);
        File sourceFile = new File(sourcePath);

        InputStream inputStream = new BufferedInputStream(new FileInputStream(sourceFile));
        OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(copyFile));

        byte[] temp = new byte[1024];
        int length;
        while ((length = inputStream.read(temp)) != -1) {
            outputStream.write(temp, 0, length);
        }
        inputStream.close();
        outputStream.close();
    }

    /**
     * 删除目录下文件
     *
     * @param path
     */
    public static void deleteFiles(String path) {
        File[] files = new File(path).listFiles();

        for (File i : files
        ) {
            i.delete();
        }
    }

    /**
     * 将File转成MultipartFile
     *
     * @param file
     * @return
     * @throws IOException
     */
    public static MultipartFile file2multipartFile(File file) throws IOException {
        FileInputStream input = new FileInputStream(file);
        return new MockMultipartFile(file.getName(), file.getName(), ContentType.APPLICATION_OCTET_STREAM.toString(), input);
    }

}
